package com.ocom.mqsimple.business.student;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ocom.common.constant.MapKey;
import com.ocom.common.dto.Department;
import com.ocom.common.entity.card.EntityXfAccountInfo;
import com.ocom.common.entity.master.EntityFileDownloadInfo;
import com.ocom.common.request.simple.StudentExcelRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.CommonUtil;
import com.ocom.common.utils.RandomUtil;
import com.ocom.common.utils.excel.SXSSFWORKBookUtils;
import com.ocom.common.vo.simple.ListVo;
import com.ocom.common.vo.simple.PersonVo;
import com.ocom.mqsimple.config.StudentExcelMqConfig;
import com.ocom.mqsimple.feign.AccessClientService;
import com.ocom.mqsimple.feign.HumanClientService;
import com.ocom.mqsimple.feign.MinioClientService;
import com.ocom.mqsimple.feign.PayConfigClientService;
import com.rabbitmq.client.Channel;
import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;


@Component
public class StudentExcelConsumerMqListener {

	private Logger logger = LoggerFactory.getLogger(StudentExcelConsumerMqListener.class);

	@Value("${save.path}")
	String excelPath;

	@Autowired
	MinioClientService minioClientService;

	@Autowired
	HumanClientService humanClientService;


	@Autowired
	AccessClientService accessClientService;

	@Autowired
	PayConfigClientService payConfigClientService;

//	@Resource
//	RedisUtil redisUtil;


	/**
	 * 把该监听命名为A监听
	 * 监听队列  远程服务支付接口发送消息  该队列会接受
	 * [message, headers, channel]
	 * @return {@link }
	 * @throws
	 */
	@RabbitListener(queues =StudentExcelMqConfig.STUDENT_EXCEL_QUEUE)
	public void process(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
		logger.info("STUDENT_EXCEL_QUEUE 消费中");
		logger.info("message【{}】",message);
		String humanMessage = new String(message.getBody(), StandardCharsets.UTF_8);
		//TODO 数据库操作样例
		logger.info("STUDENT_EXCEL_QUEUEE-start:【{}】",humanMessage);
		logger.info("System.currentTimeMillis()【{}】",System.currentTimeMillis());


		StudentExcelRequest studentExcelRequest= JSON.parseObject(humanMessage, StudentExcelRequest.class);

//		File dir = new File(zipPath);
//		dir.mkdir();

		long startTime = System.currentTimeMillis();
		String filePath = excelPath+ RandomUtil.getRandomString(32) +".xlsx";
		File file=new File(filePath);

		EntityFileDownloadInfo entityFileDownloadInfo=new EntityFileDownloadInfo();
		entityFileDownloadInfo.setId(studentExcelRequest.getId().longValue());

		//创建一个文件
		try {
			//创建Excel文件薄
			HSSFWorkbook workbook=new HSSFWorkbook();
			//创建工作表sheeet
			workbook.createSheet();
			//判断文件或文件夹是否存在
			boolean flag = file.exists();
			if(flag)
			{
				//文件存在就要删除文件
				file.delete();
			}
			file.createNewFile();
			FileOutputStream stream= FileUtils.openOutputStream(file);
			workbook.write(stream);
			stream.close();
		}catch (Exception e){
			e.printStackTrace();
		}finally {

		}


		//获取所有片区
		JSONObject jsonObject2=new JSONObject();
		jsonObject2.put("comId",studentExcelRequest.getComId());
		List<JSONObject> objectList=new ArrayList<>();

		Result result4 = accessClientService.getRegionInfo(jsonObject2);
		if(result4.getCode()==200 && result4.getData()!=null){
			JSONObject studentJSON =JSON.parseObject(JSON.toJSONString(result4.getData()));
			objectList=JSON.parseArray(JSON.toJSONString(studentJSON.get("list")),JSONObject.class);
		}

		SXSSFWorkbook sxssfWorkbook = null;
		BufferedOutputStream outputStream = null;
		try {
			//这样表示SXSSFWorkbook只会保留100条数据在内存中，其它的数据都会写到磁盘里，这样的话占用的内存就会很少
			sxssfWorkbook = new SXSSFWorkbook(SXSSFWORKBookUtils.getXSSFWorkbook(filePath),100);
			//获取第一个Sheet页
			SXSSFSheet sheet = sxssfWorkbook.getSheetAt(0);

			Map<String, Object> map = new HashMap<>();

			MapKey mapKey = new MapKey();
			Department department=new Department();
			department.setComId(studentExcelRequest.getComId());
			department.setDeptId(studentExcelRequest.getDeptId());
			department.setShowLevel(0);
			Result result23=humanClientService.getDeptIds(department);
			if (result23.getCode()!=200){
				throw new RuntimeException("部门接口异常");
			}
			map.put(mapKey.getKey_deptIds(),studentExcelRequest.getDeptId()+","+JSON.parseObject(JSON.toJSONString(result23.getData())).getString("deptIds"));
			map.put(mapKey.getKey_comId(), studentExcelRequest.getComId());
			map.put(mapKey.getKey_pCode(),studentExcelRequest.getPCode());
			map.put(mapKey.getKey_pName(),studentExcelRequest.getPName());
			map.put(mapKey.getKey_page(),1);
			map.put(mapKey.getKey_size(),1);
			map.put(mapKey.getKey_status(),0);
			map.put(mapKey.getKey_roomPerson(),studentExcelRequest.getRoomPerson());
			map.put("regionId",studentExcelRequest.getRegionId());
			map.put("regionOrigId",studentExcelRequest.getRegionOrigId());
			map.put("regionOnline",studentExcelRequest.getRegionOnline());
			map.put("accountState",studentExcelRequest.getAccountState());
			map.put("pType",studentExcelRequest.getPType());
			map.put("status",0);
			logger.info("人员列表,map{{}}",map);
			Result result = humanClientService.PersonnelGetStudentInfo(map);

			logger.info("人员列表,map----{{}}",map);
			ListVo mjRecords = JSON.parseObject(JSON.toJSONString(result.getData()),ListVo.class);
			logger.info("人员列表,map----{{}}",map);
			//下载失败 无数据
			if(mjRecords.getTotal()<=0){
				//TODO
				entityFileDownloadInfo.setStatus(2l);
				entityFileDownloadInfo.setRemark("无有效记录");
				accessClientService.UpdateFileStatus(entityFileDownloadInfo);

				throw new RuntimeException("无有效记录");
			}

			int a = mjRecords.getTotal();
			int b = 500;
			BigDecimal aBig = new BigDecimal(a);
			BigDecimal bBig = new BigDecimal(b);
			//向上取整
			Integer pages =   (int)Math.ceil(aBig.divide(bBig).doubleValue());

			SXSSFRow row0 = sheet.createRow(0);
			row0.createCell(0).setCellValue("单位id");
			row0.createCell(1).setCellValue("部门Id");
			row0.createCell(2).setCellValue("部门名称");
			row0.createCell(3).setCellValue("编号");
			row0.createCell(4).setCellValue("人员Id");
			row0.createCell(5).setCellValue("身份证");
			row0.createCell(6).setCellValue("姓名");
			row0.createCell(7).setCellValue("手机号");
			row0.createCell(8).setCellValue("同住人数");
			row0.createCell(9).setCellValue("人员类型");
			row0.createCell(10).setCellValue("所在校区");
			row0.createCell(11).setCellValue("在校状态");
			row0.createCell(12).setCellValue("当前校区");
			row0.createCell(13).setCellValue("已到期");
			row0.createCell(14).setCellValue("账户有效期");



			for (int i = 0; i < pages; i++) {

				map.put(mapKey.getKey_deptIds(),studentExcelRequest.getDeptId()+","+JSON.parseObject(JSON.toJSONString(result23.getData())).getString("deptIds"));
				map.put(mapKey.getKey_comId(), studentExcelRequest.getComId());
				map.put(mapKey.getKey_pCode(),studentExcelRequest.getPCode());
				map.put(mapKey.getKey_pName(),studentExcelRequest.getPName());
				map.put(mapKey.getKey_page(),i+1);
				map.put(mapKey.getKey_size(),500);
				map.put(mapKey.getKey_status(),0);
				map.put(mapKey.getKey_roomPerson(),studentExcelRequest.getRoomPerson());
				map.put("regionId",studentExcelRequest.getRegionId());
				map.put("regionOrigId",studentExcelRequest.getRegionOrigId());
				map.put("regionOnline",studentExcelRequest.getRegionOnline());
				map.put("pType",studentExcelRequest.getPType());
				logger.info("人员列表,map{{}}",map);
				map.put("status",0);
				Result result1 = humanClientService.PersonnelGetStudentInfo(map);



				ListVo mjRecords1 = JSON.parseObject(JSON.toJSONString(result1.getData()),ListVo.class);

				int  z =0;
				for (Object o:mjRecords1.getList()){

					PersonVo mjRecord= JSON.parseObject(JSON.toJSONString(o),PersonVo.class);
					z++;
					SXSSFRow row = sheet.createRow(i * 500 + z);

					row.createCell(0).setCellValue(mjRecord.getComId());
					row.createCell(1).setCellValue(mjRecord.getDeptId());
					row.createCell(2).setCellValue(CommonUtil.NulltoEmpty(mjRecord.getDeptName()));
					row.createCell(3).setCellValue(CommonUtil.NulltoEmpty(mjRecord.getPCode()));
					row.createCell(4).setCellValue(mjRecord.getPId());
					row.createCell(5).setCellValue(CommonUtil.NulltoEmpty(mjRecord.getPIdentity()));
					row.createCell(6).setCellValue(CommonUtil.NulltoEmpty(mjRecord.getPName()));
					row.createCell(7).setCellValue(CommonUtil.NulltoEmpty(mjRecord.getPPhone()));
					row.createCell(8).setCellValue(CommonUtil.NulltoEmpty(mjRecord.getRoomPerson()));

					if(mjRecord.getPType()!=null){
						if(mjRecord.getPType()==102){
							row.createCell(9).setCellValue("职工");
						}
						if(mjRecord.getPType()==103){
							row.createCell(9).setCellValue("教师");
						}
						if(mjRecord.getPType()==104){
							row.createCell(9).setCellValue("学生");
						}
					}
					if(mjRecord.getRegionOrigId()!=null){
						for (JSONObject jsonObject6 : objectList) {
							String regionNameNl = jsonObject6.getString("regionName");
							Long regionId = jsonObject6.getLong("regionId");
							if (mjRecord.getRegionOrigId().equals(regionId)) {
								row.createCell(10).setCellValue(regionNameNl);
								break;
							}
						}
					}
					if(mjRecord.getRegionOnline()!=null){
						if(mjRecord.getRegionOnline()==0){
							row.createCell(11).setCellValue("离校");
						}
						if(mjRecord.getRegionOnline()==1){
							row.createCell(11).setCellValue("在校");
						}
					}
					if(mjRecord.getRegionId()!=null){
						for (JSONObject jsonObject6 : objectList) {
							String regionNameNl = jsonObject6.getString("regionName");
							Long regionId = jsonObject6.getLong("regionId");
							if (mjRecord.getRegionId().equals(regionId)) {
								row.createCell(12).setCellValue(regionNameNl);
								break;
							}
						}
					}
					if(ObjectUtil.isNotEmpty(mjRecord.getEndDate())){
//						row.createCell(13).setCellValue(DateUtil.format(mjRecord.getEndDate(),"yyyy-MM-dd"));
						row.createCell(14).setCellValue(mjRecord.getEndDate());
						Date endDate = DateUtil.parse(mjRecord.getEndDate());
						if(endDate.after(new Date())){
							row.createCell(13).setCellValue("正常");
						}else{
							row.createCell(13).setCellValue("已过期");
						}
					}

					if(ObjectUtil.isEmpty(mjRecord.getEndDate())){
						row.createCell(13).setCellValue("正常");

					}
//					Result<EntityXfAccountInfo> resultA = payConfigClientService.GetXFAccount(mjRecord.getComId(),mjRecord.getPId().intValue(),-1);
//					logger.info("人员消费账户,map{{}}",JSON.toJSONString(resultA.getData()));
//					if(resultA.getCode().equals(200)){
//						if(ObjectUtil.isNotEmpty(resultA.getData()) && ObjectUtil.isNotEmpty(resultA.getData().getEndDate())){
//							row.createCell(13).setCellValue(DateUtil.format(resultA.getData().getEndDate(),"yyyy-MM-dd"));
//						}
//
//					}
				}

//				for (int z = 1; z < 101; z++) {
//					SXSSFRow row = sheet.createRow(i * 100 + z);
//					for (int j = 0; j < 10; j++) {
//						row.createCell(j).setCellValue("你好：" + j);
//					}
//				}

			}

			outputStream = new BufferedOutputStream(new FileOutputStream(filePath));
			sxssfWorkbook.write(outputStream);
			outputStream.flush();
			sxssfWorkbook.dispose();// 释放workbook所占用的所有windows资源
		} catch (IOException e) {
			e.printStackTrace();

			entityFileDownloadInfo.setStatus(2l);
			accessClientService.UpdateFileStatus(entityFileDownloadInfo);
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
			return;

		}finally {
			if(outputStream!=null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		File file1= null;
		try {
			file1=new File(filePath);
	//		MultipartFile multipartFile=FileUtil.getMultipartFile(file1);
			Result result3 = minioClientService.upload(file1);
			//删除本地
			file.delete();
			if(result3.getCode()!=200){
				//更改状态 失败
				entityFileDownloadInfo.setStatus(2l);
				accessClientService.UpdateFileStatus(entityFileDownloadInfo);
			}else{
				JSONObject jsonObject =JSON.parseObject(JSON.toJSONString( result3.getData()));
				entityFileDownloadInfo.setStatus(1l);
				entityFileDownloadInfo.setUrl(jsonObject.getString("imageUrl"));
				accessClientService.UpdateFileStatus(entityFileDownloadInfo);
			}
			long endTime = System.currentTimeMillis();
//			System.out.println(endTime-startTime);
	
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
			logger.info("STUDENT_EXCEL_QUEUE-end:【{}】",humanMessage);
			logger.info("System.currentTimeMillis()【{}】",System.currentTimeMillis());
		} catch (Exception e) {
			logger.error("STUDENT_EXCEL_QUEUE 人员导出IO异常 【{}】",e);
			channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);//继续消费该消息
		}finally {
			try {
				file1.delete();
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				file.delete();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 把该监听命名为B监听
	 * 监听死信队列  远程服务支付接口发送消息  该队列会接受
	 * [message, headers, channel]
	 * @return {@link }
	 * @throws
	 */
	@RabbitListener(queues =  StudentExcelMqConfig.STUDENT_EXCEL_DIE_QUEUE)
	public void processForDie(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
		//死信队列放弃
		logger.info("STUDENT_EXCEL_DIE_QUEUE 死信队列放弃");

		try {
			String humanMessage = new String(message.getBody(), StandardCharsets.UTF_8);
			//TODO 数据库操作样例
			logger.info("STUDENT_EXCEL_QUEUEE-start:【{}】",humanMessage);
			logger.info("System.currentTimeMillis()【{}】",System.currentTimeMillis());
			StudentExcelRequest studentExcelRequest= JSON.parseObject(humanMessage, StudentExcelRequest.class);

			EntityFileDownloadInfo entityFileDownloadInfo=new EntityFileDownloadInfo();
			entityFileDownloadInfo.setId(studentExcelRequest.getId().longValue());
			entityFileDownloadInfo.setStatus(2l);
			entityFileDownloadInfo.setRemark("导出异常-死信队列放弃");
			accessClientService.UpdateFileStatus(entityFileDownloadInfo);
		}catch (Exception e){
			logger.info("STUDENT_EXCEL_DIE_QUEUE 死信队列处理异常 【{}】",e);
		}


		channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);

	}


}
